﻿using System.Collections.Generic;
using System.Drawing;
using System.Runtime.Versioning;
using System.Windows.Forms;

#pragma warning disable IDE0130 // 命名空间与文件夹结构不匹配
namespace zykControl
#pragma warning restore IDE0130 // 命名空间与文件夹结构不匹配
{
    /// <summary>
    /// 表示zykHFGrid的数据显示区
    /// </summary>
    /// <remarks></remarks>
    [SupportedOSPlatform("windows")]
    public class ZykHFGridRoot
    {
        private readonly List<ZykHFGridArea> mAreas = [];
        private readonly ZykHFGrid mHFGrid;
        public readonly ZykHFGridColumns Columns;

        public ZykHFGridRoot(ZykHFGrid theHFGrid)
        {
            mHFGrid = theHFGrid;
            Columns = theHFGrid.Columns;
            Font = new Font(mHFGrid.Font, FontStyle.Regular);
            FontSelected = Font;
        }

        /// <summary>
        /// 添加一个区,如果最后一个区的Key与theKey则返回找到的区,否则创建新区
        /// </summary>
        /// <param name="theKey"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public ZykHFGridArea AddArea(string theKey)
        {
            if (Count == 0 || (this[Count - 1].Key ?? "") != theKey)
            {
                var dLocation = new Point();
                if (Count == 0)
                {
                    dLocation = new Point(0, 0);
                }
                else
                {
                    dLocation.X = this[Count - 1].X;
                    dLocation.Y = this[Count - 1].Y + this[Count - 1].Height;
                }

                var dRect = new ZykHFGridArea(this, theKey, mAreas.Count, dLocation);
                mAreas.Add(dRect);
                dRect.CellSelectChanged += OnCellSelectChanged;
                dRect.RowSelectChanged += OnRowSelectChanged;
                dRect.RawCountChanged += OnRowAdded;
                return dRect;
            }
            else
            {
                return this[Count - 1];
            }
        }

        /// <summary>
        /// 用于触发行数量改变时发生的事件
        /// </summary>
        /// <remarks></remarks>
        public void OnRowAdded()
        {
            // 垂直滚动条
            mHFGrid.VScrollBar1.Maximum = GetRowCount();
            // If mHFGrid.VScrollBar1.Value > mHFGrid.VScrollBar1.Maximum Then mHFGrid.VScrollBar1.Value = mHFGrid.VScrollBar1.Maximum
        }

        /// <summary>
        /// 添加一行,如果指定Key与最后一个区相同,则在此区中添加,否则在新区中添加
        /// </summary>
        /// <param name="theKey"></param>
        /// <param name="theText"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public ZykHFGridRow AddRow(string theKey, string[] theText)
        {
            var dRect = AddArea(theKey);
            return dRect.AddRow(theText);
        }

        /// <summary>
        /// 添加一行,如果指定Key与最后一个区相同,则在此区中添加,否则在新区中添加
        /// </summary>
        /// <param name="theKey"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public ZykHFGridRow AddRow(string theKey)
        {
            var dRect = AddArea(theKey);
            return dRect.AddRow();
        }

        private bool mIsDraw = true;

        /// <summary>
        /// 关闭绘制功能以提高速度
        /// </summary>
        /// <remarks></remarks>
        public void DrawClose()
        {
            mIsDraw = false;
        }

        /// <summary>
        /// 打开绘制功能并刷新数据显示区
        /// </summary>
        /// <remarks></remarks>
        public void DrawOpen()
        {
            mIsDraw = true;
            Refresh();
        }

        /// <summary>
        /// 清除所有的数据
        /// </summary>
        /// <remarks></remarks>
        public void Clear()
        {
            mAreas.Clear();
            Refresh();
        }

        /// <summary>
        /// 获得所有行的项目数的总数
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        public int GetRowCount()
        {
            int dCount = 0;
            for (int xx = 0, loopTo = mAreas.Count - 1; xx <= loopTo; xx++)
                dCount += mAreas[xx].Count;
            return dCount;
        }

        public Color BackColorSingle { get; set; } = Color.FromArgb(200, 255, 200);
        public Color BackColorDouble { get; set; } = Color.FromArgb(255, 255, 200);
        public Color BorderColor { get; set; } = Color.Blue;
        public Color BorderColorSelected { get; set; } = Color.Red;

        public Font Font
        {
            get
            {
                return mHFGrid.Font;
            }

            set
            {
                mHFGrid.Font = value;
            }
        }

        public Font FontSelected { get; set; }
        /// <summary>
        /// 返回网格中区块的数量
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public int Count
        {
            get
            {
                return mAreas.Count;
            }
        }

        public Color ForeColor
        {
            get
            {
                return mHFGrid.ForeColor;
            }
        }

        /// <summary>
        /// 检索数据集合包含的区
        /// </summary>
        /// <param name="AredIndex">区的索引</param>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public ZykHFGridArea this[int AredIndex]
        {
            get
            {
                return mAreas[AredIndex];
            }
        }

        private int mItemHeight = 20;
        /// <summary>
        /// 数据网格的一项的高度
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public int ItemHeidht
        {
            get
            {
                return mItemHeight;
            }

            set
            {
                mItemHeight = value;
            }
        }

        public void OnColumnCountChanged()
        {
            // 水平滚动条
            int dWidth = Columns.Count;
            if (dWidth == 0)
                mHFGrid.HScrollBar1.Enabled = false;
            else
                mHFGrid.HScrollBar1.Enabled = true;
            mHFGrid.HScrollBar1.Maximum = dWidth;
        }

        public void WidthChange()
        {
            Refresh();
        }

        public bool RowKeyExist(string theKey)
        {
            for (int xx = 0, loopTo = mAreas.Count - 1; xx <= loopTo; xx++)
            {
                if ((this[xx].Key ?? "") == (theKey ?? ""))
                    return true;
            }

            return false;
        }

        /// <summary>
        /// 查找指定的行Key的行
        /// </summary>
        /// <param name="theKey"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public ZykHFGridArea? FindRowByKey(string theKey)
        {
            for (int xx = 0, loopTo = mAreas.Count - 1; xx <= loopTo; xx++)
            {
                if ((this[xx].Key ?? "") == (theKey ?? ""))
                    return this[xx];
            }

            return null;
        }

        /// <summary>
        /// 查找指定的行Key的行,此函数为了添加的特点,特意倒着查以加快速度
        /// </summary>
        /// <param name="theKey"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public ZykHFGridArea? FindRowByKey2(string theKey)
        {
            for (int xx = mAreas.Count - 1; xx >= 0; xx -= 1)
            {
                if ((this[xx].Key ?? "") == (theKey ?? ""))
                    return this[xx];
            }

            return null;
        }

        /// <summary>
        /// 返回数据的总高度
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public int Height
        {
            get
            {
                if (Count == 0)
                    return 0;
                return this[Count - 1].Y + this[Count - 1].Height;
            }
        }

        /// <summary>
        /// 返回数据的总宽度
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public int Width
        {
            get
            {
                return Columns.Width;
            }
        }

        public void Refresh()
        {
            if (mIsDraw == false)
                return;
            mHFGrid.GridBody.Refresh();
        }

        internal void OnPaint(PaintEventArgs e)
        {
            var dGraphics = e.Graphics;
            dGraphics.Clear(Color.White);
            for (int xx = 0, loopTo = Count - 1; xx <= loopTo; xx++)
                this[xx].PaintRow(dGraphics, e.ClipRectangle);
        }

        private int dSelectedRowIndex = -1;

        public ZykHFGridArea? SelectedArea
        {
            get
            {
                int dIndex = SelectedAreaIndex;
                if (dIndex < 0)
                    return null;
                return this[dIndex];
            }

            set
            {
                if (value is null)
                    return;
                value.ToSelected();
            }
        }

        public int SelectedAreaIndex
        {
            get
            {
                if (dSelectedRowIndex < 0)
                {
                    if (Count > 0)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                }
                else if (dSelectedRowIndex > Count - 1)
                {
                    return Count - 1;
                }
                else
                {
                    // 此时行数自然大于0
                    return dSelectedRowIndex;
                }
            }

            set
            {
                if (value < -1)
                    value = -1;
                if (value > Count - 1)
                    value = Count - 1;
                bool dChange = dSelectedRowIndex != value;
                dSelectedRowIndex = value;
                if (dChange == true)
                {
                    if (value < 0)
                        AreaSelectChanged?.Invoke(null);
                    else
                        AreaSelectChanged?.Invoke(this[value]);
                    if (SelectedRow is null && value >= 0)
                        this[value].SelectedRowIndex = 0;
                }
            }
        }

        /// <summary>
        /// 当选定行发生改变时触发
        /// </summary>
        /// <remarks></remarks>
        public event AreaSelectChangedEventHandler? AreaSelectChanged;

        public delegate void AreaSelectChangedEventHandler(ZykHFGridArea? theArea);

        /// <summary>
        /// 当前行改变时触发
        /// </summary>
        /// <remarks></remarks>
        public event RowSelectChangedEventHandler? RowSelectChanged;

        public delegate void RowSelectChangedEventHandler(ZykHFGridRow? theRow);

        /// <summary>
        /// 用于触发当前行改变时发生的事件
        /// </summary>
        /// <param name="theRow"></param>
        /// <remarks></remarks>
        public void OnRowSelectChanged(ZykHFGridRow? theRow)
        {
            RowSelectChanged?.Invoke(theRow);
        }

        /// <summary>
        /// 当前选定的项发生改变时触发
        /// </summary>
        /// <remarks></remarks>
        public event CellSelectChangedEventHandler? CellSelectChanged;

        public delegate void CellSelectChangedEventHandler(ZykHFGridCell theCell);

        /// <summary>
        /// 用于触发当前选定单元格改变时发生的事件
        /// </summary>
        /// <param name="theItem"></param>
        /// <remarks></remarks>
        public void OnCellSelectChanged(ZykHFGridCell theItem)
        {
            CellSelectChanged?.Invoke(theItem);
        }

        public Color SelectedRowBgColor { get; set; } = Color.FromArgb(160, 160, 255);
        public Color SelectedCellBgColor { get; set; } = Color.RoyalBlue;

        /// <summary>
        /// 获得处于某点的单元格
        /// </summary>
        /// <param name="theClientPoint"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public ZykHFGridCell? GetCellByPoint(Point theClientPoint)
        {
            var dPoint = theClientPoint;

            // Dim dRect As New Rectangle(mHFGrid.Panel1.Location, mHFGrid.Panel1.Size)
            // If dRect.Contains(dPoint) = False Then Return Nothing

            int dTop = YOffset;  // 上部的偏移量
            int dLeft = XOffset;    // 左部的偏移量
            if (ItemHeidht < 1)
                return null;

            // 偏移点的位置,以消除滚动条的影响
            dPoint.X += dLeft;
            dPoint.Y += dTop;
            // 偏移点的位置,以计算工作区的相对坐标
            // dPoint.X -= mHFGrid.Panel1.Location.X
            // dPoint.Y -= mHFGrid.Panel1.Location.Y

            // 计算所在的公共行数
            int dRowIndex = dPoint.Y / ItemHeidht;
            if (dRowIndex > GetRowCount() - 1)
                return null;
            if (dRowIndex < 0)
                return null;

            // 计算所在的列数
            int dColIndex = -1;
            for (int xx = 0, loopTo = Columns.Count - 1; xx <= loopTo; xx++)
            {
                if (Columns[xx].Visible == false)
                    continue;
                if (Columns[xx].ColumnLeft <= dPoint.X && Columns[xx].ColumnLeft + Columns[xx].Width > dPoint.X)
                {
                    dColIndex = xx;
                    break;
                }
            }

            if (dColIndex == -1)
                return null;

            // 查找到此行索引下的私有行数
            for (int xx = 0, loopTo1 = Count - 1; xx <= loopTo1; xx++)
            {
                if (this[xx].Count == 0)
                    continue;
                int dCount = this[xx].Count;
                if (dRowIndex < dCount)
                {
                    return this[xx][dRowIndex][dColIndex];
                }

                dRowIndex -= dCount;
            }

            return null;
        }

        public ZykHFGridRow? SelectedRow
        {
            get
            {
                var dArea = SelectedArea;
                if (dArea is null)
                    return null;
                return dArea.SelectedRow();
            }

            set
            {
                if (value is null)
                    return;
                value.ToSelected();
            }
        }

        public ZykHFGridCell? SelectedCell
        {
            get
            {
                var dRow = SelectedRow;
                if (dRow is null)
                    return null;
                return dRow.SelectCell;
            }

            set
            {
                if (value is null)
                    return;
                value.ToSelected();
            }
        }

        /// <summary>
        /// 向上移动选项
        /// </summary>
        /// <remarks></remarks>
        public void OnItemSelectUp()
        {
            var dCell = SelectedCell;
            if (dCell is null)
                return;
            var dItemUp = dCell.GetCellUp();
            if (dItemUp is null)
                return;
            dItemUp.ToSelected();
            Refresh();
        }

        /// <summary>
        /// 向下移动选项
        /// </summary>
        /// <remarks></remarks>
        public void OnItemSelectDown()
        {
            var dItem = SelectedCell;
            if (dItem is null)
                return;
            var dItemUp = dItem.GetCellDown();
            if (dItemUp is null)
                return;
            dItemUp.ToSelected();
            Refresh();
        }

        /// <summary>
        /// 向左移动选项
        /// </summary>
        /// <remarks></remarks>
        public void OnItemSelectLeft()
        {
            var dItem = SelectedCell;
            if (dItem is null)
                return;
            var dItemUp = dItem.GetCellLeft();
            if (dItemUp is null)
                return;
            dItemUp.ToSelected();
            Refresh();
        }

        /// <summary>
        /// 向右移动选项
        /// </summary>
        /// <remarks></remarks>
        public void OnItemSelectRight()
        {
            var dItem = SelectedCell;
            if (dItem is null)
                return;
            var dItemUp = dItem.GetCellRight();
            if (dItemUp is null)
                return;
            dItemUp.ToSelected();
            Refresh();
        }

        private void OnMouseDown(object sender, MouseEventArgs e)
        {
            var dItem = GetCellByPoint(e.Location);
            dItem?.ToSelected();
            Refresh();
        }

        /// <summary>
        /// 返回数据区的垂直偏移量,此值应该为正数
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public int YOffset
        {
            get
            {
                return (mHFGrid.VScrollBar1.Value - mHFGrid.VScrollBar1.Minimum) * ItemHeidht;
            }
        }

        /// <summary>
        /// 返回数据区的水平偏移量,此值应该为正数
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public int XOffset
        {
            get
            {
                if (mHFGrid.HScrollBar1.Enabled == false || mHFGrid.HScrollBar1.Value <= 0)
                    return 0;
                return Columns[mHFGrid.HScrollBar1.Value - 1].ColumnLeft + Columns[mHFGrid.HScrollBar1.Value - 1].Width;
            }
        }
    }
}